﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;

namespace AccompanyCabinet.Helper
{
    public class OpenLock
    {
        SerialPort sp1 = new SerialPort();
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        public void OpenLockAction(DataTable dt,int status)
        {
            string s_Serial = ConfigurationManager.AppSettings["s_Serial"].ToString();
            int s_BaudRate = Convert.ToInt32(ConfigurationManager.AppSettings["s_BaudRate"].ToString());
            int s_DataBits = Convert.ToInt32(ConfigurationManager.AppSettings["s_DataBits"].ToString());
            string s_StopBits = ConfigurationManager.AppSettings["s_StopBits"].ToString();
            string s_ParityBits = ConfigurationManager.AppSettings["s_ParityBits"].ToString();
            int s_TimerSend = Convert.ToInt32(ConfigurationManager.AppSettings["s_TimerSend"].ToString());
            if (!sp1.IsOpen)
            {
                try
                {
                    #region 打开串口
                    sp1.PortName = s_Serial;
                    sp1.BaudRate = s_BaudRate;
                    sp1.DataBits = s_DataBits;
                    switch (s_StopBits) //停止位
                    {
                        case "1":
                            sp1.StopBits = StopBits.One;
                            break;
                        case "1.5":
                            sp1.StopBits = StopBits.OnePointFive;
                            break;
                        case "2":
                            sp1.StopBits = StopBits.Two;
                            break;
                        default:
                            MessageBox.Show("停止位参数不正确!");
                            break;
                    }
                    switch (s_ParityBits)             //校验位
                    {
                        case "无":
                            sp1.Parity = Parity.None;
                            break;
                        case "奇校验":
                            sp1.Parity = Parity.Odd;
                            break;
                        case "偶校验":
                            sp1.Parity = Parity.Even;
                            break;
                        default:
                            MessageBox.Show("校验位参数不正确!");
                            break;
                    }
                    if (sp1.IsOpen == true)//如果打开状态，则先关闭一下
                    {
                        sp1.Close();
                    }
                    sp1.Open();//打开串口
                    #endregion

                    ////锁反馈事件；这个类中我们不检查跨线程的调用是否合法(因为.net 2.0以后加强了安全机制,，不允许在winform中直接跨线程访问控件的属性)
                    //CheckForIllegalCrossThreadCalls = false;    
                    //sp1.DataReceived += new SerialDataReceivedEventHandler(sp1_DataReceived);
                    //string filename = "FingerRecord.xml";
                    //XmlDocument xmldoc = new XmlDocument();
                    //xmldoc.Load(filename);
                    ////得到顶层节点列表 
                    //XmlNodeList topM = xmldoc.DocumentElement.ChildNodes;
                    #region 发送数据
                    foreach (DataRow dr in dt.Rows)
                    {

                        byte LockId = Convert.ToByte(dr["dpLockId"]);
                        byte LockNum = Convert.ToByte(dr["dpLockNum"]);

                        #region 长沙锁板
                        //byte[] sendByte = new byte[] { 0xFB, 0xDF, LockId, LockNum, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x34 };//开锁
                        //sp1.Write(sendByte, 0, sendByte.Length);
                        //System.Threading.Thread.Sleep(100);
                        #endregion

                        #region 新锁板
                        byte[] sendByte1 = new byte[] { 0xFA, 0xCE, 0xA2, LockId, LockNum };
                        byte[] crc = Make_CRC(sendByte1);
                        byte[] sendByte = new byte[] { 0xFA, 0xCE, 0xA2, LockId, LockNum, crc[0], crc[1], 0xAF, 0xEC };
                        //byte[] sendByte = new byte[] { 0xFA, 0xCE, 0xA2, 1, 1, 0xA3, 0x4E, 0xAF, 0xEC };
                        //开锁
                        sp1.Write(sendByte, 0, sendByte.Length);
                        System.Threading.Thread.Sleep(100);
                        sp1.Write(sendByte, 0, sendByte.Length);

                        #endregion
                        //删除本地缓存 的指纹
                        if (status == 1)
                        {
                            XmlDocument xd = new XmlDocument();
                            xd.Load("../DeviceData.xml");//加载XML文件
                            XmlNodeList xmlNoteList = xd.GetElementsByTagName("box");
                            foreach (XmlElement item in xmlNoteList)
                            {
                                XmlNodeList xn = item.ChildNodes;
                                if (xn[2].InnerText == LockId.ToString() && xn[3].InnerText == LockNum.ToString())
                                {
                                    xn[6].InnerText = "Unuse";
                                    xn[7].InnerText = "";
                                    xn[8].InnerText = "";
                                    xn[9].InnerText = "";
                                    xn[10].InnerText = "";
                                    xn[11].InnerText = "";
                                    xn[12].InnerText = "";
                                    xd.Save("../DeviceData.xml");
                                }
                            }
                        }
                    }
                    #endregion
                }
                catch (System.Exception ex)
                {
                    LogHelper.WriteLog("openLock", ex);
                    MessageBox.Show("COM口未调试好，请联系管理员");
                    return;
                }
                finally
                {
                    sp1.Dispose();
                }
            }
        }

        public void Dispose()
        {
            sp1.Dispose();
        }

        /// <summary>
        /// 计算CRC
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public byte[] Make_CRC(byte[] data)
        {
            byte[] buf = new byte[data.Length];// 存储需要产生校验码的数据
            for (int i = 0; i < data.Length; i++)
            {
                buf[i] = data[i];
            }
            int len = buf.Length;
            int crc = 0xFFFF;//16位
            for (int pos = 0; pos < len; pos++)
            {
                if (buf[pos] < 0)
                {
                    crc ^= (int)buf[pos] + 256; // XOR byte into least sig. byte of
                                                // crc
                }
                else
                {
                    crc ^= (int)buf[pos]; // XOR byte into least sig. byte of crc
                }
                for (int i = 8; i != 0; i--)
                { // Loop over each bit
                    if ((crc & 0x0001) != 0)
                    { // If the LSB is set
                        crc >>= 1; // Shift right and XOR 0xA001
                        crc ^= 0xA001;
                    }
                    else
                        // Else LSB is not set
                        crc >>= 1; // Just shift right
                }

            }
            //String c = Integer.toHexString(crc);
            //if (c.length() == 4)
            //{
            //    c = c.substring(2, 4) + c.substring(0, 2);
            //}
            //else if (c.length() == 3)
            //{
            //    c = "0" + c;
            //    c = c.substring(2, 4) + c.substring(0, 2);
            //}
            //else if (c.length() == 2)
            //{
            //    c = "0" + c.substring(1, 2) + "0" + c.substring(0, 1);
            //}
            string crcint = crc.ToString("x2");
            string crcstr = crcint.Substring(2, 2) + crcint.Substring(0, 2);

            byte[] returnByte = new byte[] { Convert.ToByte(crc % 256), Convert.ToByte(crc / 256) };
            return returnByte;
        }
    }
}
